#include "stdafx.h"
#include "RelativeLayout.h"
#include <iostream>
#include <algorithm>

namespace fusion
{
    namespace mode10
    {
        /*
         * RelativeLayoutParams
         */
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::LeftOf = 0;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::RightOf = 1;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::Above = 2;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::Below = 3;

        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignLeft = 4;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignRight = 5;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignTop = 6;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignBottom = 7;

        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignParentLeft = 8;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignParentRight = 9;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignParentTop = 10;
        const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::AlignParentBottom = 11;

		const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::CenterInParent = 12;
		const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::CenterParentHorizontal = 13;
		const RelativeLayout::RuleKey RelativeLayout::RelativeLayoutParams::CenterParentVertical = 14;

        void RelativeLayout::RelativeLayoutParams::InitiateRules()
        {
            for (unsigned int i = 0; i < ParamsLength; ++i)
            {
                m_rules[i] = 0;
            }
        }

        RelativeLayout::RelativeLayoutParams::RelativeLayoutParams(int width, int height):
                MarginLayoutParams(width, height),
				mAlignWithParent(false)
        {
            InitiateRules();
        }

        RelativeLayout::RelativeLayoutParams::RelativeLayoutParams(const RelativeLayoutParams& params):
                MarginLayoutParams(params),
				mAlignWithParent(false)
        {
            InitiateRules();
        }

        void RelativeLayout::RelativeLayoutParams::AddRule(RuleKey ruleKey, int ruleValue)
        {
            if (ruleKey >= ParamsLength)
            {
                return;
            }
            m_rules[ruleKey] = ruleValue;
        }

        int RelativeLayout::RelativeLayoutParams::GetRule(RuleKey ruleKey) const
        {
            if (ruleKey >= ParamsLength)
            {
                
                return 0;
            }
            return m_rules[ruleKey];
        }
        /*
         * NodeDepend
         */
        RelativeLayout::NodeDepend::NodeDepend(Ref<LayoutNode> node):
                m_node(node)
        {}

        /*
         * DependencyGraph
         */
        void RelativeLayout::DependencyGraph::Clear()
        {
            m_Nodes.clear();
            m_KeyNodes.RemoveAll();
        }

        void RelativeLayout::DependencyGraph::Add(Ref<LayoutNode> node)
        {
			// or check here
			//ASSERT(node);
            Ref<NodeDepend> depNode = new NodeDepend(node);
            m_Nodes.push_back(depNode);
			unsigned int nodeID = node->GetNodeID();
            m_KeyNodes.Add(nodeID, depNode);
        }

        /**
         * Builds a sorted list of views.
         */
        void RelativeLayout::DependencyGraph::GetSortedView(List<Ref<LayoutNode> >& sorted, const List<RuleKey>& rules)
        {
            // make sure length of list sorted is zero
            //ASSERT(0 == sorted.size());

            List< Ref<NodeDepend> > roots = FindRoots(rules);

            while (roots.size() > 0)
            {
                Ref<NodeDepend> nodeDepend = roots.front();
				List<Ref<NodeDepend> >::iterator beginIter = roots.begin();
                roots.erase(beginIter);

                unsigned int nodeID = nodeDepend->GetLayoutNode()->GetNodeID();
                sorted.push_back(nodeDepend->GetLayoutNode());

                List<Ref<NodeDepend> >& dependents = nodeDepend->BeDependentsOn;
                for (List<Ref<NodeDepend> >::iterator iter = dependents.begin(); iter != dependents.end(); ++iter)
                {
                    (*iter)->DependentsOn.Remove(nodeID);
                    if ((*iter)->DependentsOn.Size() == 0)
                    {
                        roots.push_back( (*iter) );
                    }
                }

                // check circular dependency
                //ASSERT(m_Nodes.size() >= sorted.size());
                if (m_Nodes.size() < sorted.size())
                {
                    break;
                }
            }

            //ASSERT(m_Nodes.size() == sorted.size());// should be equal
        }

        /**
         * Finds the roots of the graph. A root is a node with no dependency and
         * with [0..n] dependents.
         *
         * @param rulesFilter The list of rules to consider when building the
         *        dependencies
         *
         * @return A list of node, each being a root of the graph
         */
        List< Ref<RelativeLayout::NodeDepend> > RelativeLayout::DependencyGraph::FindRoots(const List<RuleKey>& ruleFilter)
        {
            // Find roots can be invoked several times, so make sure to clear
            // all dependents and dependencies before running the algorithm
            
			for ( List< Ref<NodeDepend> >::iterator iter = m_Nodes.begin(); iter != m_Nodes.end(); ++iter)
			{
				(*iter)->BeDependentsOn.clear();
				(*iter)->DependentsOn.RemoveAll();
			}

            // builds up the dependents and dependencies for each node of the graph
			for (List<Ref<NodeDepend> >::iterator iter = m_Nodes.begin(); iter != m_Nodes.end(); ++iter)
            {
				Ref<BaseLayoutParams> baseParams = (*iter)->GetLayoutNode()->GetLayoutParams(); 
                Ref<RelativeLayoutParams> layoutParams = dynamic_cast<RelativeLayoutParams*>(baseParams.get()); // TODO add this
				//ASSERT(layoutParams);

                // look only the rules passed in parameter,
                // this way we build only the dependencies for a specific set of rules
                for (unsigned int j = 0; j < ruleFilter.size(); ++j)
                {
                    // get a value from a rule, can be an node ID of a rule or an int
                    int ruleNodeID = layoutParams->GetRule(ruleFilter[j]);

                    if (ruleNodeID > 0)
                    {
                        // The node this node depends on
                        KeyNode::Index NodeIndex = m_KeyNodes.FindKey(ruleNodeID);
						if (KeyNode::BAD_INDEX != NodeIndex)
						{
							Ref<NodeDepend> dependency = m_KeyNodes.GetValueAt(NodeIndex);
							// skip unknowns and self dependencies
							if (dependency == NULL || dependency == (*iter))
							{
								continue;
							}
							// add the current node as a dependent
							dependency->BeDependentsOn.push_back((*iter));
							// add a dependency to the current node
							(*iter)->DependentsOn.Add(ruleNodeID, dependency);
						}
                    }
                }
            }

            List< Ref<NodeDepend> > roots;
            // finds all the roots in the graph: all nodes with no dependencies
			for (List< Ref<NodeDepend> >::iterator iter = m_Nodes.begin(); iter != m_Nodes.end(); ++iter)
            {
                if ((*iter)->DependentsOn.Size() == 0)
                {
                    roots.push_back( (*iter) );
                }
            }
            return roots;
        }

        Ref<RelativeLayout::NodeDepend> RelativeLayout::DependencyGraph::FindKeyNode(int nodeId)
        {
            KeyNode::Index index = m_KeyNodes.FindKey(nodeId);
            if (index == KeyNode::BAD_INDEX)
            {
                return NULL;
            }
            return m_KeyNodes.GetValueAt(index);
        }

        void RelativeLayout::DependencyGraph::log(List<RuleKey> rules)
        {
            List< Ref<NodeDepend> > roots = FindRoots(rules);
            for (List<Ref<NodeDepend> >::iterator iter = roots.begin(); iter != roots.end(); ++iter)
            {
                printNode(*iter);
            }
        }

        void RelativeLayout::DependencyGraph::printNode(Ref<NodeDepend> node)
        {
            if (0 == node->BeDependentsOn.size())
            {
                printNodeName(node);
            }
            else
            {
                for (List<Ref<NodeDepend> >::iterator iter = node->BeDependentsOn.begin(); iter != node->BeDependentsOn.end(); ++iter)
                {
                    if (0 != (*iter)->BeDependentsOn.size())
                    {
                        printNode((*iter));
                    }
                }
            }
        }

        void RelativeLayout::DependencyGraph::printNodeName(Ref<NodeDepend> node)
        {
        }

       const List<RelativeLayout::RuleKey> RelativeLayout::sRulesVertical =
               RelativeLayout::Create_List<RelativeLayout::RuleKey>
       (RelativeLayout::RelativeLayoutParams::Above)
       (RelativeLayout::RelativeLayoutParams::Below)
       (RelativeLayout::RelativeLayoutParams::AlignTop)
       (RelativeLayout::RelativeLayoutParams::AlignBottom);

       const List<RelativeLayout::RuleKey> RelativeLayout::sRulesHorzontal =
               RelativeLayout::Create_List<RelativeLayout::RuleKey>
       (RelativeLayout::RelativeLayoutParams::LeftOf)
       (RelativeLayout::RelativeLayoutParams::RightOf)
       (RelativeLayout::RelativeLayoutParams::AlignLeft)
       (RelativeLayout::RelativeLayoutParams::AlignRight);

       RelativeLayout::RelativeLayout(Node* node, Ref<BaseLayoutParams> params):
           LayoutGroup(node, params)
       {
           m_graph = new DependencyGraph();
       }
       RelativeLayout::~RelativeLayout()
       {
			delete m_graph;
       }

       void RelativeLayout::onMeasure(const Ref<MeasureSpec>& widthSpec, const Ref<MeasureSpec>& heightSpec)
       {
           if (m_LayoutDirty)
           {
               m_LayoutDirty = false;
               SortNodes();
           }

           int myWidth = widthSpec->Size;
           int myHeight = heightSpec->Size;

           for (List<Ref<LayoutNode> >::iterator iter = m_sortedHorizontalChildren.begin();
                   iter != m_sortedHorizontalChildren.end(); ++iter)
           {
               Ref<BaseLayoutParams> params = (*iter)->GetLayoutParams();
				Ref<RelativeLayoutParams> rParams = dynamic_cast<RelativeLayoutParams*>(params.get());
				//ASSERT(rParams);
               applyHorizontalSizeRules(rParams, widthSpec);
               measureChildHorizontal((*iter), rParams, myWidth, myHeight);
               positionChildHorizontal((*iter), rParams, myWidth);
           }
           
		   for (List<Ref<LayoutNode> >::iterator iter = m_sortedVerticalChildren.begin();
			   iter != m_sortedVerticalChildren.end(); ++iter)
		   {
			   Ref<BaseLayoutParams> params = (*iter)->GetLayoutParams();
			   Ref<RelativeLayoutParams> rParams = dynamic_cast<RelativeLayoutParams*>(params.get());
			   //ASSERT(rParams);
			   applyVerticalSizeRules(rParams, heightSpec);
			   measureChildVertical((*iter),rParams, myWidth, myHeight);
			   positionChildVertical((*iter),rParams,myHeight);
		   }
		   // since parents size won't be changed, we don't have to adjust child again
		   logMeasureResult();
       }

	   void RelativeLayout::logMeasureResult()
	   {
			// TODO do it!
		   for (List<Ref<LayoutNode> >::iterator iter = m_Nodes.begin(); iter != m_Nodes.end(); ++iter)
		   {
			   std::cout << "NodeName: " << (*iter)->GetNodeName() << " MeasuredWidth: " << (*iter)->GetMeasuredWidth() << " MeasuredHeight: " << (*iter)->GetMeasuredHeight() << std::endl;
			   
			   Ref<BaseLayoutParams> bParams = (*iter)->GetLayoutParams();
			   Ref<RelativeLayoutParams> params = dynamic_cast<RelativeLayoutParams*>(bParams.get());
			   //ASSERT(params);
			   std::cout<<"Left: " << params->mLeft.GetSize() << " Right: " <<params->mRight.GetSize() << " Top: " <<params->mTop.GetSize() << " Bottom: " << params->mBottom.GetSize() << std::endl;
		   }
	   }

	   Ref<BaseLayoutParams> RelativeLayout::onGenerateLayoutParams(const Ref<ClientParamsAdapter>& params)
	   {
			int height = params->GetHeight();
			int width = params->GetWidth();
			int leftM = params->GetMarginLeft();
			int rightM = params->GetMarginRight();
			int topM = params->GetMarginTop();
			int bottomM = params->GetMarginBottom();
			// this is suck~~
			RelativeLayoutParams* myParams = new RelativeLayoutParams(width, height);
			myParams->SetMargins(leftM,topM,rightM,bottomM);
			for (unsigned int key = 0; key < RelativeLayoutParams::ParamsLength; ++key)
			{
				myParams->AddRule(key, params->GetParams(key));
			}	
			return myParams;
	   }

       void RelativeLayout::SortNodes()
       {
           m_graph->Clear();

           for (List<Ref<LayoutNode> >::iterator iter = m_Nodes.begin(); iter != m_Nodes.end(); ++iter)
           {
               m_graph->Add((*iter));
           }

           m_sortedHorizontalChildren.clear();
           m_sortedVerticalChildren.clear();

           m_graph->GetSortedView(m_sortedHorizontalChildren, sRulesHorzontal);
           m_graph->GetSortedView(m_sortedVerticalChildren, sRulesVertical);
       }

       void RelativeLayout::applyHorizontalSizeRules(Ref<RelativeLayoutParams>& baseParams, const Ref<MeasureSpec>& widthSpec)
       {
		   Ref<RelativeLayoutParams> params = dynamic_cast<RelativeLayoutParams*>(baseParams.get());
           params->mLeft.Clear();
           params->mRight.Clear();

           Ref<RelativeLayoutParams> anchorParams = getRelatedViewParams(params, RelativeLayoutParams::LeftOf);
           if (anchorParams)
           {
               params->mRight.SetSize( anchorParams->mLeft.GetSize() - (anchorParams->GetLeftMargin() + params->GetRightMargin()) );
           }
           else if (params->mAlignWithParent && 0 != params->GetRule(RelativeLayoutParams::LeftOf))
           {
               params->mRight.SetSize( widthSpec->Size - params->GetRightMargin() );
           }		   

           anchorParams = getRelatedViewParams(params, RelativeLayoutParams::RightOf);
           if (anchorParams)
           {
               params->mLeft.SetSize( anchorParams->mRight.GetSize()+ (anchorParams->GetRightMargin() + params->GetLeftMargin()) );
           }
           else if (params->mAlignWithParent && 0 != params->GetRule(RelativeLayoutParams::RightOf))
           {
               params->mLeft.SetSize( params->GetLeftMargin() );
           }

           anchorParams = getRelatedViewParams(params, RelativeLayoutParams::AlignLeft);
           if (anchorParams)
           {
               params->mLeft.SetSize( anchorParams->mLeft.GetSize()+ params->GetLeftMargin() );
           }
           else if (params->mAlignWithParent && 0 != params->GetRule(RelativeLayoutParams::AlignLeft))
           {
               params->mLeft.SetSize( params->GetLeftMargin() );
           }

           anchorParams = getRelatedViewParams(params, RelativeLayoutParams::AlignRight);
           if (anchorParams)
           {
               params->mRight.SetSize( anchorParams->mRight.GetSize() - params->GetRightMargin() );
           }
           else if (params->mAlignWithParent && 0 != params->GetRule(RelativeLayoutParams::AlignRight))
           {
               params->mRight.SetSize( widthSpec->Size - params->GetRightMargin() );
           }

           if (0 != params->GetRule(RelativeLayoutParams::AlignParentLeft))
           {
               params->mLeft.SetSize(params->GetLeftMargin());
           }

           if (0 != params->GetRule(RelativeLayoutParams::AlignParentRight))
           {               
               params->mRight.SetSize( widthSpec->Size - params->GetRightMargin() );
           }
       }

       void RelativeLayout::measureChildHorizontal(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myWidth, int myHeight)
       {
		   Ref<MeasureSpec> childWidthSpec = getChildMeasureSpec(params->mLeft, params->mRight, params->GetWidth(),
			   params->GetLeftMargin(), params->GetRightMargin(), myWidth);
		   Ref<MeasureSpec> childHeightSpec;
		   if (params->GetWidth() == BaseLayoutParams::MATCH_PARENT)
		   {
			   childHeightSpec = MeasureSpec::GenerateMeasureSpec(myHeight, MeasureSpec::EXACTLY);
		   } else {
			   childHeightSpec = MeasureSpec::GenerateMeasureSpec(myHeight, MeasureSpec::AT_MOST);
		   }
		   node->Measure(childWidthSpec, childHeightSpec);
       }

	   void RelativeLayout::positionChildHorizontal(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myWidth)
	   {
		   if (!params->mLeft.IsSet() && params->mRight.IsSet() )
		   {
				// Right is fixed, left varies
			   params->mLeft.SetSize( params->mRight.GetSize() - node->GetMeasuredWidth());
		   } else if (params->mLeft.IsSet() && !params->mRight.IsSet())
		   {
			   // Left is fixed, right varies
			   params->mRight.SetSize(params->mLeft.GetSize() + node->GetMeasuredWidth());
		   } else if (!params->mLeft.IsSet() && !params->mRight.IsSet())
		   {
			   // Both left and right vary
			   if (params->GetRule(RelativeLayoutParams::CenterInParent) != 0 || params->GetRule(RelativeLayoutParams::CenterParentHorizontal) != 0)
			   {
				   centerHorizontal(node, params, myWidth);  
			   } else {
				   params->mLeft.SetSize(params->GetLeftMargin());
				   params->mRight.SetSize(params->mLeft.GetSize() + node->GetMeasuredWidth());
			   }
		   }
	   }

	   void RelativeLayout::centerHorizontal(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myWidth)
	   {
		   int childWidth = node->GetMeasuredWidth();
		   int left = (myWidth - childWidth)/2;

		   params->mLeft.SetSize(left);
		   params->mRight.SetSize(left + childWidth);
	   }

	   void RelativeLayout::applyVerticalSizeRules(Ref<RelativeLayoutParams>& params, const Ref<MeasureSpec>& heightSpec)
	   {
			params->mTop.Clear();
			params->mBottom.Clear();

			Ref<RelativeLayoutParams> anchorParams = getRelatedViewParams(params, RelativeLayoutParams::Above);
			if (anchorParams)
			{
				params->mBottom.SetSize( anchorParams->mTop.GetSize() - (anchorParams->GetTopMargin() + params->GetBottomMargin()));
			} else if (params->mAlignWithParent && params->GetRule(RelativeLayoutParams::Above) != 0)
			{
				params->mBottom.SetSize(heightSpec->Size - params->GetBottomMargin());
			}

			anchorParams = getRelatedViewParams(params, RelativeLayoutParams::Below);
			if (anchorParams)
			{
				params->mTop.SetSize( anchorParams->mBottom.GetSize() + anchorParams->GetBottomMargin() + params->GetTopMargin());
			} else if (params->mAlignWithParent && params->GetRule(RelativeLayoutParams::Below) != 0)
			{
				params->mTop.SetSize(params->GetTopMargin());
			}

			anchorParams = getRelatedViewParams(params, RelativeLayoutParams::AlignTop);
			if (anchorParams)
			{
				params->mTop.SetSize( anchorParams->mTop.GetSize() + params->GetTopMargin());
			} else if (params->mAlignWithParent && params->GetRule(RelativeLayoutParams::AlignTop) != 0)
			{
				params->mTop.SetSize(params->GetTopMargin());
			}

			anchorParams = getRelatedViewParams(params, RelativeLayoutParams::AlignBottom);
			if (anchorParams)
			{
				params->mBottom.SetSize(anchorParams->mBottom.GetSize() - params->GetBottomMargin());
			} else if (params->mAlignWithParent && params->GetRule(RelativeLayoutParams::AlignBottom)!=0)
			{
				params->mBottom.SetSize(heightSpec->Size - params->GetBottomMargin());
			}

			if (0 != params->GetRule(RelativeLayoutParams::AlignParentTop))
			{
				params->mTop.SetSize(params->GetTopMargin());
			}

			if (0 != params->GetRule(RelativeLayoutParams::AlignParentBottom))
			{
				params->mBottom.SetSize(heightSpec->Size - params->GetBottomMargin());
			}
	   }

	   void RelativeLayout::measureChildVertical(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myWidth, int myHeight)
	   {
		   Ref<MeasureSpec> widthSpec = getChildMeasureSpec(params->mLeft, params->mRight, params->GetWidth(), 
			   params->GetLeftMargin(), params->GetRightMargin(), myWidth);
		   Ref<MeasureSpec> heightSpec = getChildMeasureSpec(params->mTop, params->mBottom, params->GetHeight(),
			   params->GetTopMargin(), params->GetBottomMargin(), myHeight);
		   node->Measure(widthSpec, heightSpec);
	   }

	   void RelativeLayout::positionChildVertical(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myHeight)
	   {
		   if (!params->mTop.IsSet() && params->mBottom.IsSet())
		   {
			   // Bottom is fixed, top varies
			   params->mTop.SetSize(params->mBottom.GetSize() - node->GetMeasuredHeight());
		   } else if (params->mTop.IsSet() && !params->mBottom.IsSet())
		   {
			   // Top is fixed, bottom varies
			   params->mBottom.SetSize(params->mTop.GetSize() + node->GetMeasuredHeight());
		   } else if (!params->mTop.IsSet() && !params->mBottom.IsSet()) {
			   // Both top and bottom varies
			   if (0 != params->GetRule(RelativeLayoutParams::CenterInParent) || 0 != params->GetRule(RelativeLayoutParams::CenterParentVertical)) {
				   centerVertical(node, params, myHeight);
			   } else {
				   params->mTop.SetSize(params->GetTopMargin());
				   params->mBottom.SetSize(params->mTop.GetSize() + node->GetMeasuredHeight());
			   }
		   }
	   }

	   void RelativeLayout::centerVertical(Ref<LayoutNode>& node, Ref<RelativeLayoutParams>& params, int myHeight)
	   {
		   int childHeight = node->GetMeasuredHeight();
		   int top = (myHeight - childHeight) / 2;

		   params->mTop.SetSize(top);
		   params->mBottom.SetSize(top + childHeight);
	   }
       /*
        * Get a measure spec that accounts for all of the constraints on this view.
        * This includes size constraints imposed by the Relativelayout as well as
        * the View's desired dimension.
        *
        * @param childStart The left or top field of the child's layout params
        * @param childEnd The right or bottom field of the child's layout params
        * @param childSize The child's desired size (the width or height field of
        *                  the child's layout params)
        * @param startMargin The left or top margin
        * @param endMargin The right or bottom margin
        * @param mySize The width or height of this view (the RelativeLayout)
        * @return MeasureSpec for the child
        */
	   Ref<MeasureSpec> RelativeLayout::getChildMeasureSpec(PositionIndexer& start, PositionIndexer& end, 
		   int childSize, // original size, >0 means has size, <0 means wrap or fill
		   int startMargin, int endMargin, int parentWidth)
	   {
			Ref<MeasureSpec> childSpecMode = MeasureSpec::GenerateMeasureSpec(0, MeasureSpec::UNSPECIFIED);
			
			int tempStart = start.IsSet() ? start.GetSize() : startMargin;
			int tempEnd = end.IsSet() ? end.GetSize() : childSize - endMargin;
			// Figure out maximum size available to this view
			int maxAvailable = tempEnd - tempStart;

			if (start.IsSet() && end.IsSet())
			{
				childSpecMode->Mode = MeasureSpec::EXACTLY;
				childSpecMode->Size = maxAvailable;
			} else if (childSize > 0) {
				childSpecMode->Mode = MeasureSpec::EXACTLY;
				childSpecMode->Size = childSize;
			} else if (childSize == BaseLayoutParams::MATCH_PARENT) {
				childSpecMode->Mode = MeasureSpec::EXACTLY;
				childSpecMode->Size = parentWidth;
			} else if (childSize == BaseLayoutParams::WRAP_CONTENT) {
				if (maxAvailable >= 0)
				{
					childSpecMode->Mode = MeasureSpec::AT_MOST;
					childSpecMode->Size = maxAvailable;
				} // else = UnSpecified
			}
			return childSpecMode;
	   }

       Ref<RelativeLayout::RelativeLayoutParams> RelativeLayout::getRelatedViewParams(Ref<RelativeLayoutParams> params, RuleKey ruleKey)
       {
           Ref<LayoutNode> relatedNode = getRelatedView(params, ruleKey);
           if (relatedNode)
           {
			   Ref<BaseLayoutParams> bParams = relatedNode->GetLayoutParams();
			   Ref<RelativeLayoutParams> params = dynamic_cast<RelativeLayoutParams*>(bParams.get());
			   //ASSERT(params);
               return params;
           }
           return NULL;
       }

       Ref<LayoutNode> RelativeLayout::getRelatedView(Ref<RelativeLayoutParams> params, RuleKey ruleKey)
       {
           int ruleValue = params->GetRule(ruleKey);
           if (0 != ruleValue)
           {
               Ref<NodeDepend> depend = m_graph->FindKeyNode(ruleValue);
               if (!depend)
               {
                   return NULL;
               }
               Ref<LayoutNode> node = depend->GetLayoutNode();
               return node;
           }
           return NULL;
       }
    }
}